# -*- coding: utf-8 -*-



## ------------------------------------------------------------
## Copyright 2010 Pierre-Antoine Delsart
## 
## This file is part of LeVin.
## 
## LeVin is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
## 
## LeVin is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with LeVin.  If not, see <http://www.gnu.org/licenses/>.
## ---------------------------------------------------------------


# Form implementation generated from reading ui file 'wineBase2.ui'
#
# Created: Mon Oct 25 16:50:26 2010
#      by: PythonQt UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!

from PythonQt import QtCore, QtGui
from collections import namedtuple

import wineBase
import datetime
from qtcommon import *

from wineAreas import wineWorld, wineColors

connect = QtCore.QObject.connect

class Entry(object):
    attribute =''
    label =''
    defaultv=''
    guitype = None
    editGui = None

    getCurrentCountry = None
    getCurrentRegion  = None
    getCurrentColor   = None

    cepageEntry    = None
    appelEntry     = None

    def __init__(self, att, label, defaultv):
        self.attribute = att
        self.label = label
        self.defaultv = defaultv


    def setupGui(self):
        self.qtlab.setText( self.label)        
        
        self.setup()

    def setup(self):
        pass

    def createGuiElt(self, parent,):
        k = self.attribute
        lab = QtGui.QLabel(parent)
        lab.setObjectName("newB_%s_lab"%(k,))
        elt = self.guitype( parent)
        elt.setObjectName("newB_%s"%(k,) )

        self.qtlab = lab
        self.qtelt = elt
        return (lab,elt)

    def writableCopy(self):
        return self.__class__( self.attribute, self.label, self.defaultv )

    def getValue(self):
        return self.attribute , self.currentValue()
    
    def reset(self):
        self.qtelt.clear()
        self.setup()

class ComboEntry(Entry):
    guitype = QtGui.QComboBox
    editable = True
    activationSignal = QtCore.SIGNAL("activated(int)")
    connected = False
    def setup(self):
        addItem = self.qtelt.addItem
        self.qtelt.setEditable(self.editable)
        for i,v in enumerate( self.defaultv) :
            addItem(  v )
        if not self.connected:
            self.connect()
            self.connected = True
    def currentValue(self):
        txt = unicode(self.qtelt.currentText())
        return txt if txt !='' else None
    def updateFromW(self,w):
        t = getattr(w,self.attribute)
        if t is None :
            return
        ind = self.getIndex(t)
        #print 'update ',t,'  at ', ind
        self.qtelt.setCurrentIndex(ind)
        return ind
    def getIndex(self, t):
        ind=self.qtelt.findText(t)
        if ind == -1:
            self.qtelt.addItem(  t  )
            ind = self.qtelt.count() -1
        return ind
    def connect(self):
        pass
    
class WColorComboEntry(ComboEntry):
    editable=False
    
    def getIndex(self, t):
        return t
    def setup(self):
        addItem = self.qtelt.addItem
        self.qtelt.setEditable(self.editable)
        for i,v in enumerate( self.defaultv) :
            addItem( v )
        connect(self.qtelt, self.activationSignal, self.cepageEntry.refresh)            
    def currentValue(self):
        return self.qtelt.currentIndex()

class CountryComboEntry(ComboEntry):
    subArea = None
    def connect(self):
        connect(self.qtelt, self.activationSignal, self.updateSubArea)

    def updateSubArea(self, *args):
        #print 'AreaComboEntry updateSubArea called'
        self.subArea.qtelt.clear()
        self.subArea.defaultv = wineWorld[ self.getCurrentCountry() ].subAreasKeys()
        self.subArea.setup()
        self.subArea.updateSubArea()        
    def updateFromW(self,w):
        ind=ComboEntry.updateFromW(self,w)
        self.updateSubArea( )

class RegionComboEntry(ComboEntry):
    def connect(self):    
        connect(self.qtelt, self.activationSignal, self.cepageEntry.refresh)
        connect(self.qtelt, self.activationSignal, self.appelEntry.refresh)

    def updateSubArea(self, *args):
        #print 'AreaComboEntry updateSubArea called'
        self.cepageEntry.refresh()
        self.appelEntry.refresh()

    def updateFromW(self,w):
        ind=ComboEntry.updateFromW(self,w)
        self.updateSubArea( )

class CepageComboEntry(ComboEntry):    

    def refresh(self, *args):
        #print self , 'refresh '
        self.qtelt.clear()
        self.defaultv = wineWorld[ self.getCurrentCountry() ][self.getCurrentRegion()].cepages( self.getCurrentColor() )
        self.setup()

class AppelComboEntry(ComboEntry):            
    def refresh(self, *args):
        #print self , 'refresh '        
        self.qtelt.clear()
        self.defaultv = wineWorld[ self.getCurrentCountry() ][self.getCurrentRegion()].appellations()
        self.setup()
    
class LineEditEntry(Entry):
    guitype  = QtGui.QLineEdit    
    def setupLine(self):
        self.qtelt.setText(  self.defaultv  )
    def currentValue(self):
        txt = unicode(self.qtelt.text()) 
        return txt.strip() if txt !='' else None
    def updateFromW(self,w):
        t = getattr(w,self.attribute)
        if t is None :
            return
        self.qtelt.setText( t)
        
class SpinBoxEntry(Entry):
    guitype = QtGui.QSpinBox
    def setup(self):
        v, min , max, step = self.defaultv
        print v,min,max,step
        self.qtelt.setMinimum(min)
        self.qtelt.setMaximum(max)
        self.qtelt.setSingleStep(step)
        self.qtelt.setProperty("value", v)        
    def currentValue(self):
        return self.qtelt.value()
    def updateFromW(self,w):
        t = getattr(w,self.attribute)
        if t is None :
            return
        self.qtelt.setValue( t)
        
class DoubleSpinBoxEntry(SpinBoxEntry):
    guitype = QtGui.QDoubleSpinBox
        
    
class DateEditEntry(Entry):
    guitype = QtGui.QDateEdit
    def setup(self):
        #self.qtelt.setDate(QtCore.QDate(self.defaultv[0],1,1))
        self.qtelt.setDate(self.defaultv[0])
        format = self.defaultv[1]
        if format != '':
            self.qtelt.setDisplayFormat(format)
        self.sformat = getattr(wineBase.BottleSet, self.attribute).date_string
    def currentValue(self):
        #sformat = getattr(wineBase.BottleSet, self.attribute).date_string
        return self.qtelt.date().toPyDate().strftime( self.sformat)
    def updateFromW(self,w):
        t = getattr(w,self.attribute)
        if t is None :
            return
        d=datetime.datetime.strptime( t, self.sformat)
        self.qtelt.setDate( QtCore.QDate(d.year, d.month, d.day))

class TextEditEntry(Entry):
    guitype = QtGui.QFrame

    def createGuiElt(self, parent):
        lab, wid = Entry.createGuiElt(self, parent)
        
        wid.setLineWidth(1)
        wid.setFrameStyle(1)
        self.verticalLayout = QtGui.QVBoxLayout(wid)
        self.toolBar = QtGui.QToolBar(wid)
        self.verticalLayout.addWidget(self.toolBar)
        self.textedit = QtGui.QTextEdit(wid)
        self.verticalLayout.addWidget(self.textedit)
        self.verticalLayout.setSpacing(1)

        self.addUrl_action = QtGui.QAction(wid)

        #self.addUrl_action.setIcon()
        self.addUrl_action.setText("url")    
        self.addUrl_action.setObjectName("addUrl_action")
        
        self.toolBar.addAction(self.addUrl_action)

        self.urlDialog = UrlDialog()
        self.urlDialog.parent = parent

        connect(self.addUrl_action, QtCore.SIGNAL("triggered()"), self.insertUrl);
        return lab,wid
        
    def setup(self):
        pass
    def currentValue(self):
        return unicode(self.textedit.document().toHtml())
    def updateFromW(self,w):
        t = getattr(w,self.attribute)
        if t is None :
            return
        #self.qtelt.document().setPlainText( t )
        self.textedit.setHtml( t )

    def insertUrl(self):
        tc = self.textedit.textCursor()
        res = self.urlDialog.exec_(tc.selectedText())
        if res is None:
            return
        # else res is a tuple
        replace = u'<a href="%s">%s</a>'%(res[1], res[0])
        tc.removeSelectedText()
        tc.insertHtml( replace )
        pass

    def reset(self):
        self.textedit.clear()
        self.setup()


class UrlDialog(object):
    dialog = None
    parent = None
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        #Dialog.resize(400, 164)
        self.verticalLayout = QtGui.QVBoxLayout(Dialog)
        self.verticalLayout.setObjectName("verticalLayout")
        self.label = QtGui.QLabel(Dialog)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        self.text_lineEdit = QtGui.QLineEdit(Dialog)
        self.text_lineEdit.setObjectName("text_lineEdit")
        self.verticalLayout.addWidget(self.text_lineEdit)
        self.label_2 = QtGui.QLabel(Dialog)
        self.label_2.setObjectName("label_2")
        self.verticalLayout.addWidget(self.label_2)
        self.target_lineEdit = QtGui.QLineEdit(Dialog)
        self.target_lineEdit.setObjectName("target_lineEdit")
        self.verticalLayout.addWidget(self.target_lineEdit)
        self.buttonBox = QtGui.QDialogButtonBox(Dialog)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.retranslateUi(Dialog)
        QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), Dialog.accept)
        QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def exec_(self,selected):
        if self.dialog is None:
            self.dialog = QtGui.QDialog(self.parent)
            self.setupUi( self.dialog)
        self.text_lineEdit.setText( selected)
        self.target_lineEdit.setText( selected)
        res = self.dialog.exec_()
        if not res:
            return None
        return (self.text_lineEdit.text() , self.target_lineEdit.text() )
    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(tr("Insert web link"))
        self.label.setText(tr("text"))
        self.label_2.setText(tr("target"))



DefaultEntry = namedtuple("da","name guitype label defaultcontent")

def _loadCepages():
    l = [c.decode('utf-8') for c in open(getData('cepages.txt')).read().split('\n')]
    print l
    return l

class EntryList(object):
    thelist = []
    def append(self, l):
        thel = self.thelist
        for e in l:
            setattr(self,e.attribute,e)
            thel.append(e)
    def setWritable(self):
        for e in self.thelist:
            self.writableCopy()




currentDate = QtCore.QDate.currentDate()
class Ui_Form(object):
    lastValues = None

    country_entry = CountryComboEntry("country" , tr("Country")  , wineWorld.subAreasKeys())
    region_entry =  RegionComboEntry("region" , tr("Region") , [])
    country_entry.subArea = region_entry
    Entry.appelEntry = AppelComboEntry("appellation" , tr("Appellation"),[])
    color_entry = WColorComboEntry("color" , tr("Color") , wineColors)
    Entry.cepageEntry = CepageComboEntry("cepage" , tr("Grape variety"), [])#_loadCepages()),
    entries= [
        country_entry,
        region_entry,
        color_entry,
        Entry.appelEntry,
        LineEditEntry("cru_name" , tr("Vintage"),""),
        DateEditEntry("millesime" , tr("Vintage year"),[currentDate,'yyyy']),
        SpinBoxEntry("optimalMin" , tr("Optimal starts"),[currentDate.year(),0,1000000,1]),
        SpinBoxEntry("optimalMax" , tr("Optimal ends"),[currentDate.year(),0,1000000,1]),
        Entry.cepageEntry,
        SpinBoxEntry("volume" , tr("Volume"),[75,0,10000,25]),
        DoubleSpinBoxEntry("alcohol" , tr("Alcohol"),[13,10,20,0.5]),
        LineEditEntry("productor" , tr("Productor"),""),
        SpinBoxEntry("numInStock" , tr("Number of bottles"),[6,0,1000000,1]),
        DoubleSpinBoxEntry("pricePerBottle" , tr("Bottle price"),[10., 0.,100000.,1]),
        DateEditEntry("acquireDate" , tr("Acquisition date"),[currentDate,'']),
        LineEditEntry("acquireComment" , tr("Comments on acquisition"),""),
        TextEditEntry('otherInfo', tr("Description"),""),
    ]


    Entry.getCurrentCountry = country_entry.currentValue
    Entry.getCurrentRegion  = region_entry.currentValue
    Entry.getCurrentColor   = color_entry.currentValue
    Entry.getCurrentAppellation   = Entry.appelEntry.currentValue    

    isSetup = False
    def setupUi(self, Form):        
        if self.isSetup:
            return
        Entry.editGui = self
        
        self.isSetup = True
        self.Form = Form
        Form.setObjectName("Form")
        Form.resize(412, 505)
        self.verticalLayout = QtGui.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")

        self.tabWidget = QtGui.QTabWidget(Form)


        self.entries_frame = QtGui.QFrame(Form)
        self.entries_frame.setFrameShape(QtGui.QFrame.StyledPanel)
        self.entries_frame.setFrameShadow(QtGui.QFrame.Raised)
        self.entries_frame.setObjectName("entries_frame")
        self.gridLayout = QtGui.QGridLayout(self.entries_frame)
        self.gridLayout.setObjectName("gridLayout")

        self.tabWidget.addTab(self.entries_frame, tr("Wine informations"))

        self.createWineEntries()
        

        self.tastingWid = QtGui.QWidget(self.tabWidget)
        self.tastingLayout =  QtGui.QVBoxLayout(self.tastingWid)
        self.tastingList =    QtGui.QListWidget(self.tastingWid)        
        self.tastingtoolBar = QtGui.QToolBar(self.tastingWid)

        addAction=self.tastingtoolBar.addAction("add",self.bla)
        editAction=self.tastingtoolBar.addAction("edit",self.bla)
        supressAction=self.tastingtoolBar.addAction("supress",self.bla)

        self.tastingLayout.addWidget( self.tastingList)
        self.tastingLayout.addWidget( self.tastingtoolBar)


        import editTasting
        addTastingDialog = editTasting.Ui_Dialog()
        addTastingDialog.setupUi( self.tastingWid)
        addTastingDialog.setVisible(False)
        self.addTastingDialog = addTastingDialog

        self.tastingLayout.addWidget( self.addTastingDialog.widget())
        #self.tastingLayout.addItem( QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)  )
        self.tastingLayout.addItem( QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum)  )

        self.tabWidget.addTab(self.tastingWid, tr("Tastings"))

        self.verticalLayout.addWidget(self.tabWidget)
        self.final_buttonBox = QtGui.QDialogButtonBox(Form)        
        self.final_buttonBox.setObjectName("final_buttonBox")
        self.nextBottle_button = QtGui.QPushButton(self.final_buttonBox)
        self.nextBottle_button.setText( tr( "Finish") )
        self.final_buttonBox.addButton(self.nextBottle_button ,QtGui.QDialogButtonBox.YesRole )
        self.final_checkbox = QtGui.QCheckBox(self.final_buttonBox)
        self.final_checkbox.setText( tr("Several records") )
        self.final_buttonBox.addButton(self.final_checkbox ,QtGui.QDialogButtonBox.ApplyRole )
        self.final_buttonBox.addButton(QtGui.QDialogButtonBox.Cancel)
        self.verticalLayout.addWidget(self.final_buttonBox)
        
        
        
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
        connect(self.final_buttonBox, QtCore.SIGNAL("accepted()"), self.saveBottle)
        #connect(self.nextBottle_button, QtCore.SIGNAL("clicked()"), self.nextBottle)
        connect(self.final_buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
        connect(self.final_checkbox, QtCore.SIGNAL("clicked()"), self.changeFinalButton)
        
        self.shortCut_Cc = QtGui.QShortcut("Ctrl+c",Form)
        connect(self.shortCut_Cc, QtCore.SIGNAL("activated()"), self.reject)
        self.shortCut_Cret = QtGui.QShortcut("Ctrl+return",Form)
        connect(self.shortCut_Cret, QtCore.SIGNAL("activated()"), self.saveBottle)

        #connect(self.tastingList, QtCore.SIGNAL("clicked()"), self.selectedTasting)
        connect(addAction, QtCore.SIGNAL("triggered()"), self.addTasting);
        connect(editAction, QtCore.SIGNAL("triggered()"), self.editTasting);
        connect(supressAction, QtCore.SIGNAL("triggered()"), self.supressTasting);        
        connect(self.addTastingDialog.cancelButton,QtCore.SIGNAL("clicked()"), self.cancelTasting)
        connect(self.addTastingDialog.okButton,QtCore.SIGNAL("clicked()"), self.validateTastingEdition)        

        self.Form = Form

        self.last_tastings = []

        #self.fillFunction = fillFunction
        self.editMode = False
        self.recomputeMeanRate = False

    def reject(self):
        print 'rejecting'
        self.cancelTasting()
        return self.Form.reject()
        

    def execDialogEditTasting(self, editMode , editedB=None):
        pass
    def execDialog(self, editMode , editedB=None):
        self.last_bottle = []
        self.editMode = editMode
        self.final_checkbox.setVisible(not editMode)
        if editMode:
            self.fillFunction = wineBase.updateBottleFunction(editedB)
        else:
            self.clear()
            self.fillFunction = wineBase.fillNewBottle
        self.addTastingDialog.setVisible(False)
        return self.Form.exec_()
        
    def createWineEntries(self):
        c = 0
        for entry in self.entries:
            lab, elt = entry.createGuiElt( self.entries_frame)
            self.gridLayout.addWidget(lab, c, 0, 1, 1)
            self.gridLayout.addWidget(elt, c, 1, 1, 1)            
            setattr( self, entry.attribute , entry)
            c+=1


    def finalButtonClicked(self, b):
        print 'finalButtonClicked, ', b

    def saveBottle(self):
        sameEntry , v = self.getValues()
        if self.recomputeMeanRate:
            if self.last_tastings != []:
                mr = sum( t['rate'] for t in self.last_tastings)/len(self.last_tastings)
                v['meanrate'] = mr
            else:
                v['meanrate'] = None
        if not sameEntry or  self.editMode :
            #print 'saving !',
            #print ' Tastings ==', self.last_tastings
            self.last_bottle.append(  self.fillFunction(v , self.last_tastings) )
        else:
            print ' not recording twice the same bottle'
        
        if self.final_checkbox.isChecked():
            self.nextBottle()
        else:
            self.last_tastings=[]
            self.addTastingDialog.clear()
            self.tastingList.clear()            
            self.Form.accept()

    def getValues(self):
        values = [e.getValue() for e in self.entries]
        values = dict ( (k,v) for (k,v) in values if v is not None )
        sameEntry = (values == self.lastValues)
        self.lastValues = values
        return sameEntry, self.lastValues
    
    def nextBottle(self):
        self.country.qtelt.setFocus()
        self.clear()

    def clear(self):
        for e in self.entries:
            e.reset()
        self.last_tastings=[]
        self.addTastingDialog.clear()
        self.tastingList.clear()


    def changeFinalButton(self):
        print 'checked !'
        if self.final_checkbox.isChecked():
            self.nextBottle_button.setText( tr("Next"))
        else:
            self.nextBottle_button.setText( tr("Finish"))
    def retranslateUi(self, Form):
        Form.setWindowTitle(tr("Edit wine entry"))
        for entry in self.entries:
            entry.setupGui()

    def updateFromWine(self, w):
        for e in self.entries:
            e.updateFromW( w )
        self.last_tastings = [ t.dic() for t in w.tastings ]
        self.updateTastingsList()
        
    def addTasting(self):
        i=self.tastingList.currentRow()
        self.addTastingDialog.clear()            
        self.addTastingDialog.setVisible(True)
        self.addTastingMode = True

    def editTasting(self):
        i=self.tastingList.currentRow()        
        if i < len(self.last_tastings):
            print 'prepare edit ',i, self.last_tastings
            self.addTastingDialog.update(self.last_tastings[i])
        #self.addTastingDialog.updateFromB()
        self.addTastingDialog.setVisible(True)            
        self.addTastingMode = False
        
    def supressTasting(self):
        i=self.tastingList.currentRow()
        del(self.last_tastings[i])
        self.updateTastingsList()
        self.recomputeMeanRate = True        
        
    def updateTastingsList(self):
        print self.last_tastings
        self.tastingList.clear()
        for t in self.last_tastings:
            com = t['comment']
            com = com[:16] if com else ''
            self.tastingList.addItem(str(t['date'])+tr(", ")+str(t['rate'])+"/10, "+com )
        
    def validateTastingEdition(self):
        values = self.addTastingDialog.currentValues()
        print 'validated tasting ', values
        if self.addTastingMode:
            self.last_tastings.append( values)
        else:
            i=self.tastingList.currentRow()
            print 'edit tasting line ',i            
            self.last_tastings[i] = values
        self.addTastingDialog.setVisible(False)
        self.updateTastingsList()
        self.recomputeMeanRate = True

    def cancelTasting(self):
        self.addTastingDialog.setVisible(False)
        
    def bla(self):
        print self.tastingList.currentRow()
        print 'AAA'

_editWine = None
def getEditWineUI():
    if _editWine :
        return _editWine
    return Ui_Form()
